﻿/// <reference path="vant/vant.min.js" />
(function (jscript, undefined) {
    $.extend(jscript, {
        config: { reqType: 0, link: '', key: '' },
        ready: function (option) {
            var self = this;
            $.each(option, function (idx, item) {
                if (self.config.hasOwnProperty(idx)) {
                    self.config[idx] = item;
                }
            });
        },
        element: { elVue: new Vue({}), loading: null, loadingCount: 0 },
        mask: function (text) {
            var self = this;
            text = text || '请稍后...';
            if (!!vant) {
                if (self.element.loadingCount == 0) {
                    self.element.loading = vant.Toast.loading({
                        message: text || '加载中...',
                        forbidClick: true,
                        duration: 0
                    });
                }
                Vue.nextTick(function () {
                    if (!!self.element.loading) self.element.loading.message = text;
                });
                self.element.loadingCount++;
            }
        },
        unmask: function () {
            var self = this;
            if (!!vant) {
                Vue.nextTick(function () {
                    self.element.loadingCount--;
                    self.element.loadingCount = Math.max(self.element.loadingCount, 0);
                    if (self.element.loadingCount == 0) !!self.element.loading && self.element.loading.clear();
                });
            }
        },
        postSuccess: function (res) {
            var self = this;
            if (res.code == -999) {
                self.msg(res.errmsg, function () {
                    window.top.location.replace(res.data.url);
                });
                return true;
            }
            return false;
        },
        postERR: function (msg) {
            var self = this;
            self.alert(msg, '未知错误');
        },
        // 询问框
        confirm: function (msg, yes, btn2, success, title) {
            var self = this;

            if (!!vant) {
                var box = vant.Dialog.confirm({
                    title: title || '提示',
                    message: msg,
                    messageAlign: 'left',
                    allowHtml: true,
                    type: 'warning',
                    closeOnClickOverlay: false,
                    showCancelButton: true,
                    closeOnPopstate: false,
                    beforeClose: function (action, done) {
                        if ('confirm' === action) {
                            self.isFunction(yes) && yes.call(self);
                        }
                        else {
                            self.isFunction(btn2) && btn2.call(self);
                        }
                        done();
                    }
                }).catch(function () { });

                if (self.isFunction(success)) {
                    success.call(self, box);
                }
            }
        },
        // 提示框
        msg: function (msg, fn, time, ic) {
            if (!msg) return;
            var self = this, vue = self.element.elVue;
            if (!!vue) {
                vue.$notify({
                    dangerouslyUseHTMLString: true,
                    message: msg,
                    duration: time || 3000,
                    type: ic || 'primary',
                    className: 'text-left flex-row-stretch',
                    onClose: function () {
                        self.isFunction(fn) && fn.call(self);
                    }
                });
            }
        },
        success: function (msg, fn, time) {
            var self = this;
            self.msg(msg, fn, time, 'success');
        },
        error: function (msg, fn, time) {
            var self = this;
            self.msg(msg, fn, time, 'danger');
        },
        // 弹框
        alert: function (message, title, yes, success) {
            var self = this;
            if (!!vant) {
                var box = vant.Dialog.alert({
                    title: title || '提示',
                    message: message,
                    messageAlign: 'left',
                    allowHtml: true,
                    theme: 'round-button',
                    confirmButtonText: '确定',
                    confirmButtonColor: '#00B1FF',
                    closeOnClickOverlay: false,
                    showCancelButton: false,
                    closeOnPopstate: false,
                    beforeClose: function (action, done) {
                        if (action === 'confirm') {
                            self.isFunction(yes) && yes.call(self);
                        }
                        done();
                    }
                });
                if (self.isFunction(success)) {
                    success.call(self, box);
                }
            }
        },
        alertX: function (option) {
            option = option || {};
            var self = this, _default = {
                title: '',
                message: (function () {
                    var str = '<div style="text-align:center;" class="wrap">';
                    var icon = option.type == 'success' ? 'checked color-green' : option.type == 'danger' ? 'warning color-red' : option.type == 'warning' ? 'warning color-orange' : 'info color-blue';
                    str += '<div><i class="van-icon van-icon-{0}" style="font-size:70px;"></i></div>'.formatStr(icon);
                    if (!!option.title) {
                        str += '<div style="margin-top:20px;font-size:18px;color:#333;">' + option.title + '</div>';
                    }
                    str += '<div style="text-align:center;color:#666;margin-top:20px;line-height:22px;font-size:14px;">' + option.msg + '</div>';
                    str += '</div>';
                    return str;
                })(),
                messageAlign: 'left',
                allowHtml: true,
                theme: 'round-button',
                confirmButtonText: option.btnTxt || '确定',
                confirmButtonColor: option.btnColor || '#00B1FF',
                closeOnClickOverlay: false,
                showCancelButton: false,
                closeOnPopstate: false,
                beforeClose: function (action, done) {
                    done();
                    if (action === 'confirm') {
                        self.isFunction(option.ok) && option.ok.call(self);
                    }
                }
            };
            if (!!vant) {
                var box = vant.Dialog.alert(_default);
            };
        },
        // 加载层
        load: function (text) {
            this.mask(text);
        },
        hideload: function () {
            this.unmask();
        },
        emptyComponent: function (text) {
            return '<van-empty description="' + text + '" />';
        },
        /**
         * 公共 验证element表单，验证不通过滚动到第一个错误
         * @param {Vue} vue vue实例
         * @param {String} formName el-form的ref
         * @param {Function} success 验证通过执行的函数
         */
        validateElForm: function (vue, formName, success, fail) {
            var self = this, form = !!vue && !!formName && !!vue.$refs ? vue.$refs[formName] : null;
            if (!form || !self.isFunction(form.validate)) return;
            form.validate(function (valid, object) {
                if (!valid) {
                    vue.$nextTick(function () {
                        var el = document.getElementsByClassName('is-error');
                        self.scrollIntoView(el);
                    });
                    if (self.isFunction(fail)) fail.call(self);
                    else self.isFunction(success) && self.error('验证有误，请检查');
                    return false;
                }
                self.isFunction(success) && success.call(self);
            });
        },
        /**
         * 公共vxe-table验证
         * @param {any} options
         */
        validVXETable: function (options) {
            var self = this
                , o = {
                    table: !!options && !!options.table && self.isFunction(options.table.validate) ? options.table : null, //vxt-table实例
                    success: !!options && self.isFunction(options.success) ? options.success : function () { }, //验证成功执行的回调
                    fail: !!options && self.isFunction(options.fail) ? options.fail : function (err) { self.error(err); } //验证失败执行的回调
                };

            if (!o.table) {
                return o.fail('要验证的数据表为空');
            }
            var msgList = [];
            o.table.validate(true, function (errMap) {
                if (!!errMap) {
                    $.each(errMap, function (key, val) {
                        $.each(val, function (ix0, params) {
                            $.each(params.rules, function (ix1, rule) {
                                msgList.push('第 {0} 行 {1} 校验错误：{2}'.formatStr(params.rowIndex + 1, params.column.title, rule.message))
                            });
                        });
                    });
                    o.fail.call(self, msgList.join('<br/>'));
                }
                else {
                    o.success.call(self);
                }
            });
        },
        fileCover: function () {
            var self = this;
            return {
                template: '<label class="flex-column" style="vertical-align:middle;align-items:center;justify-content:center;overflow:hidden;position:relative;cursor: pointer;user-select:none;"><input title="点击选择文件" ref="file" type="file" v-on:change="selectFile" :accept="accept" style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; opacity: 0; cursor: pointer; user-select: none; display:none;" /><div><slot></slot></div></label>',
                props: {
                    accept: {
                        type: String,
                        default: ''
                    },
                    size: {
                        type: Number,
                        default: 209715200 //200M
                    }
                },
                methods: {
                    selectFile: function (e) {
                        var _this = this, files = e.target.files;
                        if (files.length == 0) return;
                        var file = files[0];
                        _this.$refs['file'].value = '';
                        if (file.size > _this.size) return self.error('文件最大不可超过' + self.getFileSize(_this.size));
                        _this.$emit('change', file);
                    }
                }
            };
        },
        /**
         * 生成二维码
         * */
        qrcode: function () {
            var self = this;
            return {
                template: '<img :src="qrcode" />',
                props: {
                    value: {
                        type: String,
                        default: ''
                    },
                    width: {
                        type: Number,
                        default: 200
                    }
                },
                data: function () {
                    return {
                        qrcode: null
                    };
                },
                watch: {
                    value: function (val) {
                        this.setCode(val);
                    }
                },
                created: function () {

                },
                mounted: function () {
                    this.setCode(this.value);
                },
                methods: {
                    setCode: function (val) {
                        var _this = this;
                        QRCode.toDataURL(val, {
                            errorCorrectionLevel: 'M',
                            width: _this.width,
                            margin: 2,
                            color: { dark: '#000000', light: '#ffffff' }
                        }, function (err, url) {
                            _this.qrcode = url;
                        });
                    }
                }
            };
        },
        remoteScript: function () {
            return {
                render: function (createElement) {
                    var self = this;
                    return createElement('script', {
                        attrs: {
                            type: 'text/javascript',
                            src: self.src
                        },
                        on: {
                            load: function (event) {
                                self.$emit('load', event);
                            },
                            error: function (event) {
                                self.$emit('error', event);
                            },
                            readystatechange: function (event) {
                                if (this.readyState == 'complete') {
                                    self.$emit('load', event);
                                }
                            }
                        }
                    });
                },
                data: function () {
                    return {

                    };
                },
                props: {
                    src: {
                        type: String,
                        required: true
                    }
                }
            };
        },
        remoteStyle: function () {
            return {
                render: function (createElement) {
                    var self = this;
                    return createElement('link', {
                        attrs: {
                            rel: 'stylesheet',
                            type: 'text/css',
                            lang:'scss',
                            href: self.src
                        },
                        on: {
                            load: function (event) {
                                self.$emit('load', event);
                            },
                            error: function (event) {
                                self.$emit('error', event);
                            },
                            readystatechange: function (event) {
                                if (this.readyState == 'complete') {
                                    self.$emit('load', event);
                                }
                            }
                        }
                    });
                },
                props: {
                    src: {
                        type: String,
                        required: true
                    }
                }
            };
        },
        wxPay: function (data, callback) {
            var jsApiCall = function () {
                WeixinJSBridge.invoke('getBrandWCPayRequest', {
                    "appId": data.appId,
                    "timeStamp": data.timeStamp,
                    "nonceStr": data.nonceStr,
                    "package": data.pkg,
                    "signType": data.signType,
                    "paySign": data.paySign
                }, function (res) {
                    callback(res)
                });
            }
            if (typeof WeixinJSBridge == "undefined") {
                if (document.addEventListener) {
                    document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
                }
                else if (document.attachEvent) {
                    document.attachEvent('WeixinJSBridgeReady', jsApiCall);
                    document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
                }
            }
            else {
                jsApiCall();
            }
        },
        floatButton: function () {
            return {
                template: '<a ref="floatButton" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend" @click="btnClick" style="position: fixed;z-index: 999;padding:8px;display: flex; justify-content: center; align-items: center; background-image: linear-gradient(-225deg, #5D9FFF 0%, #B8DCFF 48%, #6BBBFF 100%); border-radius: 50%; color:#00B1FF;" :style="{left: left + \'px\',top: top + \'px\',opacity:opacity}"><slot></slot></a>',
                props: {
                    gapWidth: {
                        // 距离左右两边距离
                        type: Number,
                        'default': 5,
                    },
                    initTop: {
                        // 从上到下距离比例
                        type: Number,
                        'default': 0.6,
                    }
                },
                data: function () {
                    return {
                        top: 0,
                        left: 0,
                        currentTop: 0,
                        clientWidth: 0,
                        clientHeight: 0,
                        timer: null,
                        opacity: 0.75,
                        itemWidth: 0,
                        itemHeight: 0
                    };
                },
                created: function () {

                },
                mounted: function () {
                    var _this = this;
                    _this.$nextTick(function () {
                        var floatButton = _this.$refs.floatButton;
                        //元素大小
                        _this.itemHeight = floatButton.offsetHeight;
                        _this.itemWidth = floatButton.offsetWidth;
                        // 手机大小
                        _this.clientWidth = document.documentElement.clientWidth;
                        _this.clientHeight = document.documentElement.clientHeight;
                        //初始位置
                        _this.left = _this.clientWidth - _this.itemWidth - _this.gapWidth;
                        _this.top = _this.clientHeight * _this.initTop;
                    });
                },
                methods: {
                    // 点击事件
                    btnClick: function () {
                        this.$emit('click');
                    },
                    touchstart: function (e) {
                        var _this = this, floatButton = _this.$refs.floatButton;
                        //e.preventDefault();
                        _this.opacity = 1;
                        floatButton.style.transition = 'none';
                    },
                    touchmove: function (e) { //在拖拽过程中，组件应该跟随手指的移动而移动
                        var _this = this, floatButton = _this.$refs.floatButton;
                        e.preventDefault();
                        if (e.targetTouches.length === 1) {
                            // 一根手指
                            _this.opacity = 1;
                            var touch = e.targetTouches[0];
                            _this.left = touch.clientX - 20;
                            _this.top = touch.clientY - 25;
                        }
                    },
                    touchend: function (e) {
                        var _this = this, floatButton = _this.$refs.floatButton;
                        _this.opacity = 0.75;
                        floatButton.style.transition = 'all 0.3s';

                        if (_this.top < _this.gapWidth) {
                            _this.top = _this.gapWidth;
                        }
                        else if (_this.top > _this.clientHeight - _this.itemHeight) {
                            _this.top = _this.clientHeight - _this.itemHeight - _this.gapWidth;
                        }

                        if (_this.left > document.documentElement.clientWidth / 2) {
                            _this.left = _this.clientWidth - _this.itemWidth - _this.gapWidth;
                        } else {
                            _this.left = _this.gapWidth;
                        }
                    }
                }
            };
        },
        pageTip: function () {
            return {
                template: (function () {
                    var str = '<van-empty image-size="100px">';
                    str += '<template #image v-if="!!ico">';
                    str += '<van-loading v-if="ico==\'loading\'" size="90" color="#5FB878"></van-loading>';
                    str += '<van-icon v-else :name="ico" size="90" :class="[color]"></van-icon>';
                    str += '</template>';
                    str += '<template #description>';
                    str += '<div style="text-align:center;">';
                    str += '<slot name="title"><div v-if="!!title" style="color:#000;font-size:16px;margin-bottom:15px;">{{title}}</div></slot>';
                    str += '<slot><div v-if="!!msg" v-html="msg"></div></slot>';
                    str += '</div>';
                    str += '</template>';
                    str += '<van-button v-if="!!btn" type="info" round style="width:80vw;" :url="url" replace @click="btnClick">{{btn}}</van-button>';
                    str += '<slot name="btns"></slot>';
                    str += '</van-empty>';
                    return str;
                })(),
                props: {
                    type: {
                        type: String,
                        'default': 'info'
                    },
                    icon: {
                        type: String,
                        'default': ''
                    },
                    title: {
                        type: String,
                        'default': ''
                    },
                    msg: {
                        type: String,
                        'default': '',
                    },
                    btn: {
                        type: String,
                        'default': ''
                    },
                    url: {
                        type: String,
                        'default': ''
                    }
                },
                computed: {
                    ico: function () {
                        if (!!this.icon) return this.icon;
                        else if (this.type == 'none') return null;
                        else if (this.type == 'loading') return 'loading';
                        else if (this.type == 'warning' || this.type == 'danger') return 'warning';
                        else if (this.type == 'success') return 'checked';
                        else if (this.type == 'clock') return 'clock-o';
                        else return 'info';
                    },
                    color: function () {
                        return this.type == 'warning' ? 'color-orange' : this.type == 'danger' ? 'color-red' : this.type == 'success' ? 'color-green' : 'color-blue-1';
                    }
                },
                methods: {
                    btnClick: function () {
                        this.$emit('btnClick');
                    }
                }
            };
        },
        hxtLayout: function () {
            var hxt = this;
            return {
                template: (function () {
                    var str = '<div>';
                    str += '<page-tip v-if="!!feeTip" type="warning" :title="feeTip.title" :msg="feeTip.msg" :btn="feeTip.btn" :url="feeTip.url"></page-tip>';
                    str += '<page-tip v-else-if="!!error" type="danger" :msg="error" btn="返回主页" :url="homeUrl"></page-tip>';
                    str += '<slot v-else></slot>';
                    str += '</div>';
                    return str;
                })(),
                props: {
                    fee: {
                        type: Number,
                        'default': 0
                    },
                    error: {
                        type: String,
                        'default': ''
                    },
                    //是否验证服务状态
                    status: {
                        type: Boolean,
                        'default': function () {
                            return true;
                        }
                    }
                },
                data: function () {
                    return {
                        optor: hxt.store.optor
                    };
                },
                computed: {
                    feeTip: function () {
                        var _this = this, hasFee = _this.fee;

                        if (!!_this.status) {
                            if (_this.optor.uiStatus == 1) {
                                return {
                                    title: '温馨提示',
                                    msg: '您已关闭{0}服务{1}。'.formatStr(_this.optor.pubCompanyShortName, (!!_this.optor.pubHotLine ? '，详询：' + _this.optor.pubHotLine : '')),
                                    btn: '返回主页',
                                    url: _this.homeUrl
                                }
                            }
                        }

                        if (hasFee == 0) return null;
                        return {
                            title: '温馨提示',
                            msg: (function () {
                                if (hasFee == 2) return '您的{0}余额（{1}元）已用完，请充值后再使用此功能。'.formatStr(_this.optor.pubCompanyShortName, _this.optor.fee_balance);
                                if (hasFee == -1) return '拉取相关参数失败，请稍后再试。';
                                if (hasFee == 1) return '您尚未开通此项服务' + (!!_this.optor.pubHotLine ? '，详询：' + _this.optor.pubHotLine : '') + '。';
                                if (hasFee == 3) return '暂停服务';
                                return '';
                            })(),
                            btn: hasFee == 2 ? '立即充值' : '返回主页',
                            url: hasFee == 2 ? '{0}?state=pay&userid={1}'.formatStr(_this.optor.pubLink, _this.optor.uiId) : _this.homeUrl
                        }
                    },
                    homeUrl: function () {
                        var _this = this;
                        return '{0}?state=userinfo&userid={1}'.formatStr(_this.optor.pubLink, _this.optor.uiId)
                    }
                },
                components: {
                    pageTip: hxt.pageTip()
                }
            };
        },
        hxtPopup: function () {
            var hxt = this;
            return {
                template: (function () {
                    //return '<van-action-sheet v-model="show" class="hidden popup" style="height:auto !important;position: fixed;max-height:85%;" position="bottom" v-on:close="show=false" :round="round" :close-on-click-overlay="closeOnClickOverlay" :closeable="closeable" :safe-area-inset-bottom="false" :get-container="getContainer">'
                    //    + '<template v-if="!!title||!!$slots.title||!!description||!!$slots.description" #description>'
                    //    + '<div v-if="!!title||!!$slots.title" class="bg-light" style="position: relative;text-align: center; padding: 16px 0 10px 0;"><slot name="title">{{title}}</slot>'
                    //    + '<van-icon v-if="!!closeable" name="cross" class="close-icon" v-on:click="show=false"></van-icon>'
                    //    + '</div>'
                    //    + '<div v-if="!!description||!!$slots.description"><slot name="description">{{description}}</slot></div>'
                    //    + '</template>'
                    //    + '<slot></slot>'                        
                    //    + '</van-action-sheet>';
                    return '<van-popup v-model="show" class="hidden van-action-sheet" style="height:auto !important;position: fixed;max-height:85%;" position="bottom" v-on:close="show=false" :round="round" :close-on-click-overlay="closeOnClickOverlay" :closeable="false" :safe-area-inset-bottom="false" :get-container="getContainer" >'
                        + '<template v-if="!!title||!!$slots.title">'
                        + '<div v-if="!!title||!!$slots.title" class="wrap bg-light flex-row solid-bottom" style="min-height: 50px; padding: 0px 16px;"><div class="flex-row-fill text-bold"><slot name="title">{{title}}</slot></div><div><van-icon name="close" v-on:click="show=false" size="20" color="#ee0a24"></van-icon></div>'
                        + '</div>'
                        + '</template>'
                        + '<slot name="description"></slot>'
                        + '<div class="van-action-sheet__content" :style="{height:contentFlex?0:\'auto\'}"><slot></slot></div>'
                        + '<slot name="foot"></slot>'
                        + '</van-popup>';
                })(),
                props: {
                    value: {
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                    closeOnClickOverlay: {//是否在点击遮罩层后关闭
                        type: Boolean,
                        default: function () {
                            return true;
                        }
                    },
                    closeable: {//是否显示关闭图标
                        type: Boolean,
                        default: function () {
                            return false;
                        }
                    },
                    round: {// 	是否显示圆角
                        type: Boolean,
                        default: function () {
                            return false;
                        }
                    },
                    title: {//标题 如果插槽有内容，则title无效
                        type: String,
                        default: function () {
                            return '';
                        }
                    },
                    contentFlex: {//兼容XP和部分ios嵌套flex:1内容不能自动撑开的问题
                        type: Boolean,
                        default: function () {
                            return false;
                        }
                    },
                    getContainer: {
                        type: [String, Function],
                        default: null
                    },
                    href: {
                        type: String,
                        default: function () {
                            return null
                        }
                    }
                },
                data: function () {
                    return {
                        key: 'hxt.popup.show.' + hxt.guid()
                    };
                },
                computed: {
                    show: {
                        get: function () {
                            return this.value;
                        },
                        set: function (val) {
                            this.$emit('input', val);
                        }
                    }
                },
                watch: {
                    show: function (val) {
                        var _this = this;
                        hxt.popupAdapter.appWatch(_this.key, !!val, function () { _this.show = false; }, _this.href);
                    },
                },
                components: {

                }
            };
        },
        hxtRefresh: function () {
            var hxt = this;
            return {
                template: (function () {
                    return '<div v-cloak class="h100 hidden-x">'
                        + '<van-pull-refresh v-model="isLoading" v-on:refresh="loadList" style="height:100%;overflow:auto;" :head-height="100">'
                        + '<div style="height:1px;"></div><slot></slot>'
                        + '<div class="padding-tb-15 padding-lr-10">'
                        + '<van-button block v-on:click="loadList(true)" v-if="hasMore&&!!moreText" :disabled="!!isLoading" round>{{!!isLoading ? "正在加载..." : moreText}}</van-button>'
                        + '<van-divider v-if="!hasMore&&!!nomoreText" class="size-12 color-999" style="margin:0;">{{nomoreText}}</van-divider>'
                        + '</div>'
                        + '</van-pull-refresh>'
                        + '</div>';
                })(),
                props: {
                    hasMore: {
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                    value: {
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                    moreText: {
                        type: String,
                        default: function () {
                            return '点击查看更多'
                        }
                    },
                    nomoreText: {
                        type: String,
                        default: function () {
                            return '没有更多信息了'
                        }
                    },
                },
                data: function () {
                    return {

                    };
                },
                computed: {
                    isLoading: {
                        get: function () {
                            return this.value;
                        },
                        set: function (val) {
                            this.$emit('input', val);
                        }
                    }
                },
                methods: {
                    loadList: function (e) {
                        var _this = this;
                        _this.$emit('loadList', e);
                    },
                },
                components: {

                }
            };
        },
        hxtSelect: function () {
            var hxt = this;
            return {
                name: 'hxtSelect',
                template: (function () {
                    return '<div v-cloak>'
                        + '<div v-on:click="openData" class="color-999">'
                        + '<div v-if="!obj" >{{placeholder}}</div>'
                        + '<div v-else :class="{\'color-black-1\':!disabled}" style="min-height:20px;">{{obj[text]}}<van-icon v-on:click.stop="value1=null" class="van-field__clear" v-if="!!obj&&clearable" size="14" name="close"></van-icon></div>'
                        + '</div>'
                        + '<hxt-popup v-model="show" round :style="{height:height}" :closeable="closeable" :close-on-click-overlay="closeOnClickOverlay" :get-container="getContainer">'
                        + '<template #title><slot name="title">{{title}}</slot></template>'
                        + '<template v-if="!!issearch" #description>'
                        + '<van-search v-model.trim="searchTxt" placeholder="请输入搜索关键词"></van-search>'
                        + '</template>'
                        + '<template v-for="item in data" :key="item[label]">'
                        + '<div v-on:click="itemClick(item)" :style="{display:search(item)}">'
                        + '<slot v-bind="item">'
                        + '<van-cell :is-link="!disabledItem(item)" :clickable="!disabledItem(item)" :value-class="{\'color-blue\':value1==item[label], \'color-888\':!!disabledItem(item)}">{{item[text]}}</van-cell>'
                        + '</slot>'
                        + '</div>'
                        + '</template>'
                        + '</hxt-popup>'
                        + '</div>';
                })(),
                props: {
                    placeholder: {
                        type: String,
                        'default': function () {
                            return '请选择...'
                        }
                    },
                    //是否禁用组件
                    disabled: {
                        type: Boolean,
                        'default': function () {
                            return false
                        }
                    },
                    //弹出框标题
                    title: {
                        type: String,
                        'default': function () {
                            return '请选择...'
                        }
                    },
                    //是否在点击遮罩层后关闭
                    closeOnClickOverlay: {
                        type: Boolean,
                        default: function () {
                            return true;
                        }
                    },
                    //是否显示关闭图标
                    closeable: {
                        type: Boolean,
                        default: function () {
                            return false;
                        }
                    },
                    value: {
                        type: Object,
                        'default': function () {
                            return null;
                        }
                    },
                    data: {
                        type: Array,
                        'default': function () {
                            return [];
                        }
                    },
                    //绑定值对应的属性名
                    label: {
                        type: String,
                        'default': function () {
                            return '';
                        }
                    },
                    //显示值对应的属性名
                    text: {
                        type: String,
                        'default': function () {
                            return '';
                        }
                    },
                    //禁用选项对应的属性名
                    disprop: {
                        type: String,
                        'default': function () {
                            return '';
                        }
                    },
                    //是否开启搜索
                    issearch: {
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                    //自定义搜索方法
                    match: {
                        type: Function,
                        'default': null
                    },
                    //弹出框高度
                    height: {
                        type: String,
                        'default': function () {
                            return 'auto';
                        }
                    },
                    getContainer: {
                        type: [String, Function],
                        default: null
                    },
                    clearable: {//是否可清空
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                },
                data: function () {
                    return {
                        show: false,
                        searchTxt: ''
                    };
                },
                computed: {
                    value1: {
                        get: function () {
                            return this.value;
                        },
                        set: function (val) {
                            this.$emit('input', val);
                        }
                    },
                    obj: function () {
                        var _this = this;
                        if (!_this.data || !hxt.isArray(_this.data) || _this.data.length == 0 || !_this.label) return null;
                        return _this.data.find(function (x) {
                            return x[_this.label] == _this.value1;
                        });
                    }
                },
                watch: {
                    show: function (val) {
                        this.searchTxt = '';
                    }
                },
                activated: function () {

                },
                mounted: function () {

                },
                methods: {
                    openData: function () {
                        var _this = this;
                        if (!!_this.disabled) return;
                        if (!_this.$listeners['load']) {
                            if (_this.data.length == 0) return hxt.error("列表为空");
                            _this.show = true;
                            return;
                        };
                        this.$emit('load', function (res) {
                            if (res.length == 0) return hxt.error("列表为空");
                            _this.show = true;
                            _this.data = res;
                        });
                    },
                    itemClick: function (item) {
                        var _this = this;
                        if (!!_this.disabledItem(item)) return;
                        _this.value1 = item[_this.label];
                        _this.show = false;
                        _this.$emit('change', item);
                    },
                    disabledItem: function (item) {
                        return !!this.disprop && !!item[this.disprop];
                    },
                    search: function (item) {
                        var _this = this;
                        if (!_this.issearch) return 'block';
                        //未输入
                        if (!_this.searchTxt) return 'block';
                        //传入搜索函数
                        if (hxt.isFunction(_this.match)) {
                            return !!_this.match(item, _this.searchTxt) ? 'block' : 'none';
                        }
                        var txt = ('' + item[_this.text]).toUpperCase(), str = _this.searchTxt.toUpperCase();
                        return txt.indexOf(str) > -1 || hxt.pinyin(txt).indexOf(str) > -1 ? 'block' : 'none';
                    }
                },
                components: {
                    hxtPopup: hxt.hxtPopup()
                }
            };
        },
        hxtDatetimePicker: function () {
            var hxt = this;
            return {
                name: 'hxtDatetimePicker',
                template: (function () {
                    return '<div v-cloak>'
                        + '<div v-on:click="openData" class="color-999">'
                        + '<span v-if="!currentDate">{{placeholder}}</span>'
                        + '<span v-else :class="{\'color-black-1\':!disabled}">{{currentDate}}<van-icon v-on:click.stop="currentDate=null" class="van-field__clear" v-if="clearable" size="14" name="close"></van-icon></span>'
                        + '</div>'
                        + '<hxt-popup v-model="show" round :closeable="closeable" :close-on-click-overlay="closeOnClickOverlay" get-container="body">'
                        + '<div class="flex-column">'
                        + '<van-datetime-picker :type="type" v-model="timestamp" v-on:confirm="onConfirm" v-on:cancel="show=false" :title="title" :formatter="formatter" :filter="filter" :max-date="maxDate" :min-date="minDate" :min-hour="minHour" :max-hour="maxHour" :min-minute="minMinute" :max-minute="maxMinute" :show-toolbar="showToolbar" :confirm-button-text="confirmButtonText" :cancel-button-text="cancelButtonText"></van-datetime-picker>'
                        + '</div>'
                        + '</hxt-popup>'
                        + '</div>';
                })(),
                props: {
                    value: {
                        type: Object,
                        'default': function () {
                            return null;
                        }
                    },
                    title: {//标题
                        type: String,
                        'default': function () {
                            return '';
                        }

                    },
                    //是否禁用组件
                    disabled: {
                        type: Boolean,
                        'default': function () {
                            return false
                        }
                    },
                    type: {//时间类型，可选值为 date datetime year-month time
                        type: String,
                        'default': function () {
                            return 'date';
                        }
                    },
                    maxDate: {//最大时间
                        type: Object,
                        'default': function () {
                            return hxt.dateAdd('y', +1, hxt.dateFormat('yyyy-MM-dd hh:mm'));
                        }
                    },
                    minDate: {//最小时间
                        type: Object,
                        'default': function () {
                            return hxt.dateAdd('y', -1, hxt.dateFormat('yyyy-MM-dd hh:mm'));
                        }
                    },
                    maxHour: {//最大小时
                        type: Number,
                        'default': function () {
                            return 23;
                        }
                    },
                    minHour: {//最小小时
                        type: Number,
                        'default': function () {
                            return 0;
                        }
                    },
                    maxMinute: {//最大分钟
                        type: Number,
                        'default': function () {
                            return 59;
                        }
                    },
                    minMinute: {//最小分钟
                        type: Number,
                        'default': function () {
                            return 0;
                        }
                    },
                    showToolbar: {//是否显示顶部栏
                        type: Boolean,
                        'default': function () {
                            return true;
                        }
                    },
                    confirmButtonText: {//确认按钮文字
                        type: String,
                        'default': function () {
                            return '确认';
                        }
                    },
                    cancelButtonText: {//取消按钮文字
                        type: String,
                        'default': function () {
                            return '取消';
                        }
                    },
                    formatter: {//选项格式化函数(type 可能值为 year, month, day, hour, minute)
                        type: Function,
                        'default': function (type, value) {
                            if (type === 'year') {
                                return value + '年';
                            }
                            if (type === 'month') {
                                return value + '月';
                            }
                            if (type === 'day') {
                                return value + '日';
                            }
                            if (type === 'hour') {
                                return value + '时';
                            }
                            if (type === 'minute') {
                                return value + '分';
                            }
                            return value;
                        }
                    },
                    filter: {//选项过滤函数(type 可能值为 year, month, day, hour, minute)
                        type: Function,
                        'default': null
                    },
                    placeholder: {
                        type: String,
                        'default': function () {
                            return '请选择';
                        }
                    },
                    closeOnClickOverlay: {//是否在点击遮罩层后关闭
                        type: Boolean,
                        'default': function () {
                            return true;
                        }
                    },
                    closeable: {//是否显示关闭图标
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                    round: {// 	是否显示圆角
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                    clearable: {//是否可清空
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                },
                data: function () {
                    return {
                        show: false,
                        timestamp: this.type == 'time' ? this.value : hxt.dateAdd('M', 0, hxt.dateFormat('yyyy-MM-dd hh:mm', this.value || null))
                    }
                },
                computed: {
                    currentDate: {
                        get: function () {
                            return this.value;
                        },
                        set: function (val) {
                            this.$emit('input', val);
                        }
                    }
                },
                watch: {
                    value: function (val) {
                        this.timestamp = hxt.dateAdd('M', 0, hxt.dateFormat('yyyy-MM-dd hh:mm', val));
                    }
                },
                activated: function () {

                },
                mounted: function () {

                },
                methods: {
                    openData: function () {
                        var _this = this;
                        if (!!_this.disabled) return;
                        _this.show = true;
                    },
                    onConfirm: function (e) {
                        console.log(e)
                        var _this = this, formatStr = _this.type == 'year-month' ? 'yyyy-MM' : _this.type == 'datetime' ? 'yyyy-MM-dd hh:mm' : _this.type == 'time' ? 'hh:mm' : 'yyyy-MM-dd';
                        _this.currentDate = _this.type == 'time' ? e : hxt.dateFormat(formatStr, e);
                        _this.timestamp = e;
                        _this.show = false;
                    },
                    getDate: function (interval, number) {
                        return hxt.dateAdd(interval, number, hxt.dateFormat('yyyy-MM-dd hh:mm'))
                    },
                },
                components: {
                    hxtPopup: hxt.hxtPopup()
                }
            };
        },
        hxtDropbutton: function () {
            var hxt = this;
            return {
                template: (function () {
                    return '<div v-cloak style="display:inline-block;">'
                        + '<div class="clickarea" v-on:click.stop="showMenu">'
                        + '<slot><van-icon name="ellipsis" class="size-16 color-gray" style="font-weight: bold;"></van-icon></slot>'
                        + '</div>'
                        + '<div :style="!mask?\'display: none;\':\'\'">'
                        + '<div class="mask" v-on:click="hideMenu"></div>'
                        + '<div id="menus" :class="[\'menus\', animationcl]" :style="{\'top\':top,\'right\':right,\'left\':left,\'bottom\':bottom}" v-on:click="hideMenu"><slot name="items"></slot></div>'
                        + '</div>'
                        + '<template v-else>';
                    + '<div style="display: none;"><slot name="items"></slot></div>';
                    + '</template>';
                    + '</div>';
                })(),
                props: {

                },
                data: function () {
                    return {
                        mask: false,
                        left: 'auto',
                        right: 'auto',
                        top: 'auto',
                        bottom: 'auto',
                        animationcl: 'right-left'
                    };
                },
                computed: {

                },
                methods: {
                    showMenu: function (e) {
                        var _this = this,
                            innerWidth = window.innerWidth,
                            innerHeight = window.innerHeight,
                            width = $(e.target).outerWidth(true),
                            height = $(e.target).outerHeight(true),
                            p = $(e.target).offset(),
                            bottom = innerHeight - (p.top + height);

                        if (p.top >= innerHeight * 0.66) { //下面显示不下往上飘
                            if (p.left >= innerWidth / 2) {
                                _this.left = 'auto';
                                _this.bottom = bottom + 'px';
                                _this.top = 'auto';
                                _this.right = (innerWidth - p.left) + 'px';
                                _this.animationcl = 'right-left';
                            } else {
                                _this.left = (p.left + width) + 'px';
                                _this.bottom = bottom + 'px';
                                _this.top = 'auto';
                                _this.right = 'auto';
                                _this.animationcl = 'left-right';
                            }
                        } else {
                            if (p.left >= innerWidth / 2) {
                                _this.left = 'auto';
                                _this.bottom = 'auto';
                                _this.top = p.top + 'px';
                                _this.right = (innerWidth - p.left) + 'px';
                                _this.animationcl = 'right-left';
                            } else {
                                _this.left = (p.left + width) + 'px';
                                _this.bottom = 'auto';
                                _this.top = p.top + 'px';
                                _this.right = 'auto';
                                _this.animationcl = 'left-right';
                            }
                        }
                        _this.mask = true;
                    },
                    hideMenu: function () {
                        this.mask = false;
                    },
                },
                components: {

                }
            };
        },
        hxtCalendar: function () {
            var hxt = this;
            return {
                name: 'hxtCalendar',
                template: (function () {
                    return '<div v-cloak>'
                        + '<span v-if="error" class="color-999">{{error}}</span>'
                        + '<div v-on:click="openData" class="color-999" v-else>'
                        + '<span v-if="!currentDate">{{placeholder}}</span>'
                        + '<template v-else>'
                        + '<span v-if="type==\'range\'||type==\'multiple\'" :class="{\'color-black-1\':!disabled}">'
                        + '<span v-for="(item,index) in currentDate" :class="{\'block\':!connector}">'
                        + '<span class="margin-lr-4" v-if="index>0&&!!connector">{{connector}}</span>{{item}}'
                        + '</span>'
                        + '<van-icon v-on:click.stop="currentDate=null" class="van-field__clear" v-if="clearable&&!!connector" size="14" name="close"></van-icon>'
                        + '</span>'
                        + '<span v-else :class="{\'color-black-1\':!disabled}">{{currentDate}}<van-icon v-on:click.stop="currentDate=null" class="van-field__clear" v-if="clearable" size="14" name="close"></van-icon></span>'
                        + '</div>'
                        + '<van-calendar v-model="show" :default-date="timestamp" :type="type" :title="title" :show-title="showTitle" :show-subtitle="showSubtitle" :min-date="minDate" :max-date="maxDate" :show-confirm="showConfirm" :formatter="formatter" :readonly="readonly" :confirm-text="confirmText" :confirm-disabled-text="confirmDisabledText" :round="round" :close-on-click-overlay="closeOnClickOverlay" :first-day-of-week="firstDayOfWeek" :max-range="maxRange" :allow-same-day="allowSameDay" color="#1989fa" :safe-area-inset-bottom="false" get-container="body" v-on:confirm="confirm"></van-calendar>'
                        + '</div>';
                })(),
                props: {
                    value: {
                        type: Object,
                        'default': function () {
                            return null;
                        }
                    },
                    title: {//标题
                        type: String,
                        'default': function () {
                            return '日期选择';
                        }
                    },
                    connector: {//连接符 ~ 至, 赋值即表示 横向展示
                        type: String,
                        'default': function () {
                            return '';
                        }
                    },
                    disabled: { //是否禁用组件
                        type: Boolean,
                        'default': function () {
                            return false
                        }
                    },
                    type: {//选择类型:single表示选择单个日期，multiple表示选择多个日期，range表示选择日期区间
                        type: String,
                        'default': function () {
                            return 'single';
                        }
                    },
                    maxDate: {//最大时间
                        type: Object,
                        'default': function () {
                            return hxt.dateAdd('M', +6, hxt.dateFormat('yyyy-MM-dd'));
                        }
                    },
                    minDate: {//最小时间
                        type: Object,
                        'default': function () {
                            return hxt.dateAdd('M', -6, hxt.dateFormat('yyyy-MM-dd'));
                        }
                    },
                    maxRange: {//最小时间
                        type: Object,
                        'default': function () {
                            return null;
                        }
                    },
                    allowSameDay: {//最小时间
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                    showTitle: {//是否展示日历标题
                        type: Boolean,
                        'default': function () {
                            return true;
                        }
                    },
                    showSubtitle: {//是否展示日历副标题（年月）
                        type: Boolean,
                        'default': function () {
                            return true;
                        }
                    },
                    showConfirm: {//是否展示确认按钮
                        type: Boolean,
                        'default': function () {
                            return true;
                        }
                    },
                    confirmText: {//确认按钮文字
                        type: String,
                        'default': function () {
                            return '确定';
                        }
                    },
                    confirmDisabledText: {//确认按钮处于禁用状态时的文字
                        type: String,
                        'default': function () {
                            return '确定';
                        }
                    },
                    firstDayOfWeek: {//设置周起始日 0-6
                        type: Number,
                        'default': function () {
                            return 0;
                        }
                    },
                    readonly: {
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                    formatter: {//日期格式化函数
                        type: Function,
                        'default': function (day) {
                            return day;
                        }
                    },
                    placeholder: {
                        type: String,
                        'default': function () {
                            return '请选择';
                        }
                    },
                    closeOnClickOverlay: {//是否在点击遮罩层后关闭
                        type: Boolean,
                        'default': function () {
                            return true;
                        }
                    },
                    round: {// 	是否显示圆角
                        type: Boolean,
                        'default': function () {
                            return true;
                        }
                    },
                    clearable: {//是否可清空 单选以及横向展示支持清空按钮
                        type: Boolean,
                        'default': function () {
                            return false;
                        }
                    },
                    href: {
                        type: String,
                        default: function () {
                            return null
                        }
                    }
                },
                data: function () {
                    return {
                        key: 'hxt.calendar.show.' + hxt.guid(),
                        show: false,
                        timestamp: null,
                        error: ''
                    }
                },
                computed: {
                    currentDate: {
                        get: function () {
                            return this.value;
                        },
                        set: function (val) {
                            this.$emit('input', val);
                        }
                    }
                },
                watch: {
                    value: {
                        handler: function (newValue, oldValue) {
                            var _this = this;
                            if (!newValue) {
                                if (_this.type == 'range' || _this.type == 'multiple') _this.timestamp = [hxt.dateAdd('d', 0)];
                                else _this.timestamp = hxt.dateAdd('d', 0);
                                return;
                            };
                            if (hxt.isArray(newValue) && _this.type != 'range' && _this.type != 'multiple') return _this.error = "单选，v-model不能是数组";
                            if (!hxt.isArray(newValue) && (_this.type == 'range' || _this.type == 'multiple')) return _this.error = "多选，v-model必须是一个数组";
                            if (hxt.isArray(newValue)) {
                                _this.timestamp = [];
                                $.each(newValue, function (idx, item) {
                                    _this.timestamp.push(hxt.dateAdd('M', -0, hxt.dateFormat('yyyy-MM-dd', item)));
                                });
                            } else {
                                _this.timestamp = hxt.dateAdd('M', -0, hxt.dateFormat('yyyy-MM-dd', newValue));
                            };
                        },
                        immediate: true
                    },
                    show: function (val) {
                        var _this = this;
                        hxt.popupAdapter.appWatch(_this.key, !!val, function () { _this.show = false; }, _this.href);
                    },
                },
                activated: function () {

                },
                mounted: function () {

                },
                methods: {
                    openData: function () {
                        var _this = this;
                        if (!!_this.disabled) return;
                        _this.show = true;
                    },
                    confirm: function (e) {
                        var _this = this;
                        if (hxt.isArray(e)) {
                            var currentDate = [];
                            $.each(e, function (idx, item) {
                                currentDate.push(hxt.dateFormat('yyyy-MM-dd', item));
                            });
                            _this.currentDate = currentDate;
                        } else {
                            _this.currentDate = hxt.dateFormat('yyyy-MM-dd', e);
                        };
                        _this.timestamp = e;
                        _this.show = false;
                    }
                },
                components: {

                }
            };
        },
        popupAdapter: (function (hxt) {
            var obj = {
                popups: [],
                open: function (key, callback, href) {
                    var _this = this, state = {
                        old: window.history.state,
                        key: key,
                        delete: false,
                        close: function () {
                            var that = this,
                                idx = _this.popups.findIndex(function (x) { return x.key == that.key; });

                            if (idx >= 0) _this.popups.splice(idx, 1);
                            hxt.isFunction(callback) && callback();
                        }
                    };
                    _this.popups.push(state);
                    setTimeout(function () {
                        window.history.pushState(state.key, null, !!href ? href : window.location.href);
                    }, 0);
                    //console.log('pushState' + window.history.length, state.key, JSON.stringify(_this.popups));
                },
                close: function (key) {
                    var _this = this;
                    var o = _this.popups.find(function (x) { return x.key == key; });
                    if (!!o) {
                        o.delete = true;
                        window.history.back();
                    }
                },
                appWatch: function (key, val, callback, href) {
                    var _this = this;
                    if (!!key) {
                        if (val) _this.open(key, callback, href);
                        else _this.close(key);
                    }
                }
            };
            if (!!Vue) {
                var addWatch = function (el, binding, vnode) {
                    var callback = function () {
                        //console.log(binding.expression);
                        var data = vnode.context, arr = binding.expression.split('.');
                        arr.map(function (item, idx) {
                            //console.log(item);
                            if (idx != arr.length - 1) data = data[item];
                            else data[item] = false;//!!binding.arg ? binding.arg : false;
                        });
                    };
                    obj.appWatch(el.dataset.appWatchId, binding.value, callback);
                };

                Vue.directive('app-watch', {
                    bind: function (el, binding, vnode) {
                        el.dataset.appWatchId = '' + binding.expression + '#' + new Date().getTime();
                        //console.log('bind', el.dataset.appWatchId, binding.value, binding.oldValue);
                        !!binding.value && addWatch(el, binding, vnode);
                    },
                    update: function (el, binding, vnode) {
                        //console.log('update', el.dataset.appWatchId, binding.value, binding.oldValue);
                        binding.value != binding.oldValue && addWatch(el, binding, vnode);
                    },
                    unbind: function (el, binding, vnode) {
                        //console.log(binding);
                    }
                });
            }
            $(window).on('popstate', function (e) {
                var o = obj.popups.find(function (x) { return !!x.delete; });
                if (!o && obj.popups.length > 0) {
                    o = obj.popups[obj.popups.length - 1];
                    o.delete = true;
                }
                !!o && o.close();
                //if (!!o) console.log('popstate' + window.history.length, o.key, JSON.stringify(obj.popups));
            });
            return obj;
        })(window.$jscript.fn),
    });
    //指令 v-blur 使 el-button 点击后失去焦点
    Vue.use({
        install: function (app) {
            var fun = function (e) {
                var target = e.target;
                if (target.nodeName == "SPAN" || target.nodeName == "I") {
                    target = e.target.parentNode;
                }
                target.blur();
            };
            app.directive('blur', {
                inserted: function (el) {
                    el.addEventListener('click', fun, true);
                },
                unbind: function (el) {
                    el.removeEventListener('click', fun)
                }
            });
        }
    });

    Vue.directive('removeAriaHidden', {
        bind: function (el, binding) {
            var ariaEls = el.querySelectorAll('.el-radio__original');
            ariaEls.forEach(function (item) {
                item.removeAttribute('aria-hidden');
            });
        }
    });
})(window.$jscript.fn);